package com.joysuch.wwyt.attendance.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.joysuch.wwyt.attendance.bean.ParticipantBean;
import com.joysuch.wwyt.attendance.dto.AttendanceGroupDto;
import com.joysuch.wwyt.attendance.dto.AttendanceGroupShiftDto;
import com.joysuch.wwyt.attendance.entity.AttendanceGroup;
import com.joysuch.wwyt.attendance.entity.AttendanceShift;
import com.joysuch.wwyt.attendance.entity.AttendanceUser;
import com.joysuch.wwyt.attendance.mapper.AttendanceGroupMapper;
import com.joysuch.wwyt.attendance.mapper.AttendanceShiftMapper;
import com.joysuch.wwyt.attendance.mapper.AttendanceUserMapper;
import com.joysuch.wwyt.attendance.service.AttendanceGroupService;
import com.joysuch.wwyt.attendance.service.AttendanceUserService;
import com.joysuch.wwyt.attendance.util.AttendanceDayUtils;
import com.joysuch.wwyt.attendance.vo.AttendanceGroupShiftVo;
import com.joysuch.wwyt.attendance.vo.AttendanceGroupVo;
import com.joysuch.wwyt.bp.entity.BpDepart;
import com.joysuch.wwyt.bp.entity.BpJob;
import com.joysuch.wwyt.bp.repository.BpDepartDao;
import com.joysuch.wwyt.bp.repository.BpJobDao;
import com.joysuch.wwyt.core.bean.SimpleListBean;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.enums.DeleteFlag;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.support.Context;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zqw
 * @since 2022-03-01
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class AttendanceGroupServiceImpl extends ServiceImpl<AttendanceGroupMapper, AttendanceGroup> implements AttendanceGroupService {

    @Autowired
    private AttendanceGroupService groupService;

    @Autowired
    private AttendanceGroupMapper groupMapper;

    @Autowired
    private AttendanceUserMapper userMapper;

    @Autowired
    private BaseUserDao baseUserDao;

    @Autowired
    private BpDepartDao bpDepartDao;

    @Autowired
    private BpJobDao bpJobDao;

    @Autowired
    private AttendanceShiftMapper shiftMapper;

    @Autowired
    private AttendanceUserService userService;


    @Override
    public AttendanceGroup saveGroup(AttendanceGroupDto dto) throws ApiBusinessException {
        AttendanceGroup group = new AttendanceGroup();
        //获取除了本考勤组外,其他考情组最近一次的设置信息
        if (dto.getId() != null) {
            group = groupMapper.selectById(dto.getId());
            if (group == null) {
                throw new ApiBusinessException(Status.ATTENDANCE_GROUP_NOT_EXIST);
            }
            constructUserchedule(dto);
        }
        List<AttendanceGroup> otherGroupList = groupMapper.getAllGroups(dto.getId(), Context.getCompanyCode(), Context.getCurrentTenantId());
        if (!CollectionUtils.isEmpty(otherGroupList)) {
            List<String> nameList = otherGroupList.stream().map(AttendanceGroup::getGroupName).distinct().collect(Collectors.toList());
            if (nameList.contains(dto.getGroupName())) {
                throw new ApiBusinessException(Status.DUPLICATE_ATTENDANCE_GROUP_NAME);
            }
        }

        //转换group数据
        group = convertGroupSaveData(group, dto);
        //校验-一个人只能在一个考勤组
        groupCheck(otherGroupList, dto.getParticipantIds(), dto.getParticipantType());
        //生成当月/下个月 人员排班数据
        groupService.saveOrUpdate(group);
        if (dto.getAttendanceFlag().intValue() == 0) {
            createMonthData(dto.getEffectFlag(), group);
        }
        return group;
    }

    private void createMonthData(Integer effectFlag, AttendanceGroup group) {
        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        int month = now.getMonthValue();
        List<BaseUser> staffList = userService.getGroupStaffList(group, null, null);
        if (!CollectionUtils.isEmpty(staffList)) {
            List<AttendanceUser> userList = new ArrayList<>();
            if (effectFlag != null && effectFlag.intValue() == 0) {
                //当月和下个月
                userList = effectiveByMonth(userList, group, year, month);
                userList = effectiveByMonth(userList, group, year, month + 1);
            } else if (effectFlag != null && effectFlag.intValue() == 1) {
                //下个月
                userList = effectiveByMonth(userList, group, year, month + 1);
            }
            if (!CollectionUtils.isEmpty(userList)) {
                userService.saveOrUpdateBatch(userList);
            }
        }
    }

    private List<AttendanceUser> effectiveByMonth(List<AttendanceUser> userList, AttendanceGroup group, Integer year, Integer month) {

        List<AttendanceUser> oldUser = new ArrayList<>();
        if (group.getId() != null) {
            oldUser = userMapper.selectUsersByGroupIdAndYearAndMonth(group.getId(), year, month);
        }
        return userService.saveFixUserTask(group.getId(), userList, oldUser, group.getAttendanceJson(), group.getParticipantIds(),
                group.getParticipantType(), AttendanceDayUtils.getDayByMonth(year, month), 1);
    }

    @Override
    public AttendanceGroupVo findById(Long id) {
        AttendanceGroupVo bean = new AttendanceGroupVo();
        AttendanceGroup group = groupMapper.selectById(id);
        if (group == null) {
            return null;
        }
        BeanUtils.copyProperties(group, bean);
        //责任部门
        if (StringUtils.isNotBlank(group.getResDepartIds())) {
            List<Long> departIds = JSONArray.parseArray(group.getResDepartIds(), Long.class);
            List<BpDepart> departs = bpDepartDao.findByIdIn(departIds);
            List<SimpleListBean> resDeparts = new ArrayList<>();
            departs.forEach(e -> {
                resDeparts.add(new SimpleListBean(e.getId(), e.getName()));
            });
            bean.setResDeparts(resDeparts);
        }
        //参与对象
        List<ParticipantBean> groupStaffList = getParticipantList(group);
        if (!CollectionUtils.isEmpty(groupStaffList)) {
            bean.setParticipants(groupStaffList);
        }
        //考勤设置
        List<AttendanceGroupShiftVo> groupShiftVoList = getShiftBeanLisFromGroup(group);
        if (!CollectionUtils.isEmpty(groupShiftVoList)) {
            bean.setGroupShiftVoList(groupShiftVoList);
        }
        return bean;
    }


    @Override
    public List<SimpleListBean> getList() {
        List<SimpleListBean> voList = new ArrayList<>();
        List<AttendanceGroup> groupList = getLastGroupList();
        if (!CollectionUtils.isEmpty(groupList)) {
            groupList.forEach(e -> {
                voList.add(new SimpleListBean(e.getId(), e.getGroupName()));
            });
        }
        return voList;
    }

    @Override
    public List<AttendanceGroup> getGroupByAttendanceFlag(Integer attendanceFlag, String orgCode, Long tenentId) {
        return groupMapper.getGroupByAttendanceFlag(attendanceFlag, Context.getCompanyCode(), Context.getCurrentTenantId());
    }


    @Override
    public void deleteById(Long id) throws ApiBusinessException {
        AttendanceGroup group = groupMapper.selectById(id);
        if (group == null) {
            throw new ApiBusinessException(Status.ATTENDANCE_GROUP_NOT_EXIST);
        }
        group.setDeleteFlag(DeleteFlag.DELETED.getCode());
        groupMapper.updateById(group);
    }

    @Override
    public List<AttendanceGroup> getLastGroupList() {
        return groupMapper.getAllGroups(null, Context.getCompanyCode(), Context.getCurrentTenantId());
    }

    @Override
    public List<AttendanceGroupShiftVo> getShiftBeanLisFromGroup(AttendanceGroup group) {
        List<AttendanceGroupShiftVo> groupShiftVoList = new ArrayList<>();
        if (StringUtils.isNotBlank(group.getAttendanceJson())) {
            List<AttendanceGroupShiftDto> groupShiftDtos = JSONArray.parseArray(group.getAttendanceJson(), AttendanceGroupShiftDto.class);
            groupShiftDtos.forEach(e -> {
                AttendanceGroupShiftVo vo = new AttendanceGroupShiftVo();
                List<SimpleListBean> shiftList = new ArrayList<>();
                List<Long> shiftIds = e.getShiftList();
                List<AttendanceShift> shifts = shiftMapper.selectBatchIds(shiftIds);
                shifts.forEach(s -> {
                    SimpleListBean bean = new SimpleListBean();
                    bean.setId(s.getId());
                    if (s.getBreakFlag().intValue() == 1) {
                        bean.setName(s.getShiftName());
                    } else {
                        if (s.getCrossdayFlag().intValue() == 1) {
                            bean.setName(s.getShiftName() + "(" + s.getStartTime() + "-" + s.getEndTime() + "(次日))");
                        } else {
                            bean.setName(s.getShiftName() + "(" + s.getStartTime() + "-" + s.getEndTime() + ")");
                        }
                    }
                    shiftList.add(bean);
                });
                vo.setSerialNumber(e.getSerialNumber());
                vo.setShiftList(shiftList);
                groupShiftVoList.add(vo);
            });
        }
        return groupShiftVoList;
    }

    @Override
    public List<ParticipantBean> getParticipantList(AttendanceGroup group) {
        List<ParticipantBean> participants = new ArrayList<>();
        if (StringUtils.isNotBlank(group.getParticipantIds())) {
            List<Long> parIds = JSONArray.parseArray(group.getParticipantIds(), Long.class);
            if (group.getParticipantType().intValue() == 0) {
                //人员
                List<BaseUser> userList = baseUserDao.getAllByIdsAndShowState(parIds);
                if (!CollectionUtils.isEmpty(userList)) {
                    userList.forEach(e -> {
                        Optional<BpDepart> obp = bpDepartDao.findById(e.getDepartId());
                        ParticipantBean userBean = new ParticipantBean();
                        userBean.setId(e.getId());
                        userBean.setName(e.getRealName());
                        if (obp.isPresent()) {
                            userBean.setOrganizationId(obp.get().getId());
                            userBean.setOrganizationName(obp.get().getName());
                        }
                        participants.add(userBean);
                    });
                }

            } else if (group.getParticipantType().intValue() == 1) {
                //部门
                List<BpDepart> departList = bpDepartDao.findByIdIn(parIds);
                if (!CollectionUtils.isEmpty(departList)) {
                    departList.forEach(e -> {
                        ParticipantBean departBean = new ParticipantBean();
                        departBean.setId(e.getId());
                        departBean.setName(e.getName());
                        participants.add(departBean);
                    });
                }
            } else if (group.getParticipantType().intValue() == 2) {
                //岗位
                List<BpJob> jobList = bpJobDao.findAllByIds(parIds);
                if (!CollectionUtils.isEmpty(jobList)) {
                    jobList.forEach(e -> {
                        ParticipantBean jobBean = new ParticipantBean();
                        jobBean.setId(e.getId());
                        jobBean.setName(e.getName());
                        participants.add(jobBean);
                    });
                }

            }
        }
        return participants;
    }

    @Override
    public List<AttendanceShift> getGroupShiftList(AttendanceGroup group) {
        List<AttendanceShift> shiftList = new ArrayList<>();
        if (StringUtils.isNotBlank(group.getAttendanceJson())) {
            List<Long> shiftIds = new ArrayList<>();
            List<AttendanceGroupShiftDto> shiftDtos = JSONArray.parseArray(group.getAttendanceJson(), AttendanceGroupShiftDto.class);
            for (AttendanceGroupShiftDto dto : shiftDtos) {
                if (!CollectionUtils.isEmpty(dto.getShiftList())) {
                    shiftIds.addAll(dto.getShiftList());
                }
            }
            if (!CollectionUtils.isEmpty(shiftIds)) {
                shiftIds = shiftIds.stream().distinct().collect(Collectors.toList());
                shiftList = shiftMapper.selectBatchIds(shiftIds);
            }
        }
        return shiftList;
    }

    /**
     * 将现在和未来不在新的班组配置里面的人员排班删除
     *
     * @param dto
     */
    private void constructUserchedule(AttendanceGroupDto dto) {
        LocalDateTime now = LocalDateTime.now();
        int year = now.getYear();
        int month = now.getMonthValue();
        //获取当前和以后的该班组的人员排版
        List<AttendanceUser> userList = new ArrayList<>();
        userList = userMapper.selectOtherUsersByGroupIdAndYearAndGEMonth(dto.getId(), year, month);
        userList.addAll(userMapper.selectOtherUsersByGroupIdAndGTYear(dto.getId(), year));
        List<Long> parIds = dto.getParticipantIds();
        Integer type = dto.getParticipantType();
        List<BaseUser> baseUserList = new ArrayList<>();
        if (type.intValue() == 0) {
            baseUserList = baseUserDao.getAllByIds(parIds);
        } else if (type.intValue() == 1) {
            baseUserList = baseUserDao.getUsersByDepartIds(parIds, null);
        } else if (type.intValue() == 2) {
            baseUserList = baseUserDao.getUsersByJobIdsAndDepartIdAndUserName(parIds, null, null);
        }
        if (!CollectionUtils.isEmpty(baseUserList) && !CollectionUtils.isEmpty(userList)) {
            List<Long> ids = baseUserList.stream().map(BaseUser::getId).collect(Collectors.toList());
            List<AttendanceUser> deleteUsers = new ArrayList<>();
            userList.forEach(u -> {
                if (!ids.contains(u.getUserId())) {
                    u.setDeleteFlag(DeleteFlag.DELETED.getCode());
                    deleteUsers.add(u);
                }
            });
            if (!CollectionUtils.isEmpty(deleteUsers)) {
                userService.saveOrUpdateBatch(deleteUsers);
            }
        }
    }

    private AttendanceGroup convertGroupSaveData(AttendanceGroup group, AttendanceGroupDto dto) {
        BeanUtils.copyProperties(dto, group);
        //责任部门id集合
        if (!CollectionUtils.isEmpty(dto.getResDepartIds())) {
            group.setResDepartIds(JSON.toJSONString(dto.getResDepartIds()));
        } else {
            group.setResDepartIds(null);
        }
        //考勤人员id集合
        if (!CollectionUtils.isEmpty(dto.getParticipantIds())) {
            group.setParticipantIds(JSON.toJSONString(dto.getParticipantIds()));
        } else {
            group.setParticipantIds(null);
        }
        if (!CollectionUtils.isEmpty(dto.getShiftDtoList())) {
            group.setAttendanceJson(JSON.toJSONString(dto.getShiftDtoList()));
        } else {
            group.setAttendanceJson(null);
        }
        return group;
    }

    private void groupCheck(List<AttendanceGroup> otherGroupList, List<Long> participantIds, Integer
            participantType) throws ApiBusinessException {
        List<Long> otherUserIds = new ArrayList<>();
        List<Long> otherDepartIds = new ArrayList<>();
        List<Long> otherJobIds = new ArrayList<>();
        if (!CollectionUtils.isEmpty(otherGroupList)) {
            for (AttendanceGroup group : otherGroupList) {
                Integer oherParticipantType = group.getParticipantType();
                String otherParticipantIds = group.getParticipantIds();
                if (StringUtils.isNotBlank(otherParticipantIds)) {
                    List<Long> ids = JSONArray.parseArray(otherParticipantIds, Long.class);
                    if (oherParticipantType.intValue() == 0) {
                        otherUserIds.addAll(ids);
                    } else if (oherParticipantType.intValue() == 1) {
                        otherDepartIds.addAll(ids);
                    } else if (oherParticipantType.intValue() == 2) {
                        otherJobIds.addAll(ids);
                    }
                }
            }
        }
        otherUserIds = otherUserIds.stream().distinct().collect(Collectors.toList());
        Map<Long, BaseUser> userIdMap = new HashMap<>();
        if (participantType.intValue() == 0) {
            //人员
            List<BaseUser> users = baseUserDao.getAllByIdsAndShowState(participantIds);
            userIdMap = users.stream().collect(Collectors.toMap(e -> e.getId(), e -> e));
            String message = "";
            if (!CollectionUtils.isEmpty(otherDepartIds)) {
                otherUserIds.addAll(baseUserDao.getUserIdsByDepartIds(otherDepartIds));
            }
            if (!CollectionUtils.isEmpty(otherJobIds)) {
                otherUserIds.addAll(baseUserDao.getUserIdsByJobIds(otherJobIds));
            }
            for (Long userId : participantIds) {
                if (otherUserIds.contains(userId) && userIdMap.get(userId) != null) {
                    message = message + userIdMap.get(userId).getRealName() + ",";
                }
            }
            if (StringUtils.isNotBlank(message)) {
                if (message.endsWith(",")) {
                    message = message.substring(0, message.length() - 1).trim();
                }
                throw new ApiBusinessException(Status.ATTENDANCE_GROUP_USER_EXIST, message);
            }
        } else if (participantType.intValue() == 1) {
            //部门
            List<BpDepart> departs = bpDepartDao.findByIdIn(participantIds);
            Map<Long, BpDepart> departIdMap = departs.stream().collect(Collectors.toMap(e -> e.getId(), e -> e));
            String message = "";
            if (!CollectionUtils.isEmpty(otherUserIds)) {
                otherDepartIds.addAll(bpDepartDao.getDepartIdsByUserIds(otherUserIds));
            }
            if (!CollectionUtils.isEmpty(otherJobIds)) {
                otherDepartIds.addAll(bpDepartDao.getDepartIdsByJobIds(otherJobIds));
            }
            for (Long departId : participantIds) {
                if (otherDepartIds.contains(departId) && departIdMap.get(departId) != null) {
                    message = message + departIdMap.get(departId).getName() + ",";
                }
            }
            if (StringUtils.isNotBlank(message)) {
                if (message.endsWith(",")) {
                    message = message.substring(0, message.length() - 1).trim();
                }
                throw new ApiBusinessException(Status.ATTENDANCE_GROUP_DEPART_EXIST, message);
            }

        } else if (participantType.intValue() == 2) {
            //岗位
            //部门
            List<BpJob> jobs = bpJobDao.findAllByIds(participantIds);
            Map<Long, BpJob> jobIdMap = jobs.stream().collect(Collectors.toMap(e -> e.getId(), e -> e));
            String message = "";
            if (!CollectionUtils.isEmpty(otherUserIds)) {
                otherJobIds.addAll(bpJobDao.getJobIdsByUserIds(otherUserIds));
            }
            if (!CollectionUtils.isEmpty(otherDepartIds)) {
                otherJobIds.addAll(bpJobDao.getJobIdsByDepartIds(otherDepartIds));
            }
            for (Long job : participantIds) {
                if (otherJobIds.contains(job) && jobIdMap.get(job) != null) {
                    message = message + jobIdMap.get(job).getName() + ",";
                }
            }
            if (StringUtils.isNotBlank(message)) {
                if (message.endsWith(",")) {
                    message = message.substring(0, message.length() - 1).trim();
                }
                throw new ApiBusinessException(Status.ATTENDANCE_GROUP_JOB_EXIST, message);
            }
        }
    }

}
